
#ifndef _TTG_SERVICES_UPDATER_THREAD_
#define _TTG_SERVICES_UPDATER_THREAD_

#include "Common/Definitions.h"

#include <vector>
#include <list>
#include "Common/Structures.h"
#include "Runtime.Low/Threads.h"

namespace ttg_internal
{
	namespace services
	{
		//Represents single event, that should be rised after some time elapsing.
		struct TimeEvent
		{
			private:
				ttg::structures::Delegate<void, double> *loopback;
				double rate;				//in seconds.
				double start_time;			//in seconds.
				bool is_continual;
				bool is_enabled;
			public:
				//Creates required time event.
				//Note: "loopback" will be released by destructor.
				TimeEvent(ttg::structures::Delegate<void, double> *loopback,
						  double rate,
						  double start_time,
						  bool is_continual,
						  bool is_enabled)
				{
					this->loopback = loopback;
					this->rate = rate;
					this->start_time = start_time;
					this->is_continual = is_continual;
					this->is_enabled = is_enabled;
				}
				//Notifies loopback owner and resets start time.
				inline void notify(double current_time)
				{ loopback->notify(current_time); start_time = current_time; }
				//Returns rate (in seconds).
				inline double getRate()
				{ return rate; }
				//Returns left time (which can be lesser that 0.0).
				inline double getLeftTime(double current_time)
				{ return rate - (current_time - start_time); }
				//Returns true, if event should not be ignored.
				inline bool isEnabled()
				{ return is_enabled; }
				//Enables or disables current event.
				inline void setEnabled(bool value)
				{ is_enabled = value; }
				//Returns true, if event should be rised continuously.
				inline bool isContinual()
				{ return is_continual; }
				//Resets start time.
				~TimeEvent()
				{ SAFE_DELETE(loopback); }
		};
		//Performs notification for one time event.
		//Note: it's separate thread.
		class UpdaterThread :public ttg::threads::Thread
		{
			private:
				ttg::threads::FastCriticalSection locker;
				std::vector<TimeEvent *> continuous_events;
				std::list<TimeEvent *> noncontinuous_events;
				TimeEvent *current;
				bool was_modified;							//signals, that collections were modified.
				//Returns event with given ID (or NULL).
				TimeEvent *find(ttg::math::uint64 ID);
			protected:
				//Sets current event.
				//Returns required sleep time.
				double determineCurrent();
				//Thread member.
				virtual void work();
			public:
				//Creates thread, that starts updating time events.
				UpdaterThread()
					:ttg::threads::Thread(true)
				{ was_modified = false; current = NULL; }
				//Adds event and enables it. Returns event ID.
				//Note: it will be deleted by UpdaterThread.
				ttg::math::uint64 addEvent(TimeEvent *ev);
				//Disables event. It will be ignored.
				void enableEvent(ttg::math::uint64 ID);
				//Enables event. It will be rised.
				void disableEvent(ttg::math::uint64 ID);
				virtual ~UpdaterThread();
		};
	}
}

#endif
